package com.gomoku.backend.consumer;

import com.alibaba.fastjson2.JSONObject;
import lombok.Getter;
import lombok.Setter;

import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;

public class Game extends Thread{ //这里记录本局游戏的所有信息，包括棋盘大小，棋盘状态，两名玩家的id，够了
    //只需要行数和列数
    @Getter
    private final Integer rows;
    @Getter
    private final Integer cols;
    @Getter
    private final int [][] board; //每局游戏保存一个当前棋盘状态（0=空，1=黑子，2=白子）
    private final Player playerA,playerB; //对应的两名玩家
    @Getter
    private Integer currentPlayer; //玩家 1表示黑棋（初始），2白棋
    private boolean nextStepA = false; //用这两个状态来记录当前玩家是否已经落子
    private boolean nextStepB = false;
    private ReentrantLock lock = new ReentrantLock();
    private String status = "playing"; //正在游戏 ，finished游戏结束
    private String loser = ""; //all,A,B

    public Game(Integer rows,Integer cols,Integer idA,Integer idB){
        this.rows = rows;
        this.cols = cols;
        this.board = new int [rows][cols];
        this.playerA = new Player(idA,0,0,new ArrayList<>());
        this.playerB = new Player(idB,0,0,new ArrayList<>());
        this.currentPlayer = 1;
    }

    public Player getPlayerA(){
        return playerA;
    }
    public Player getPlayerB(){
        return playerB;
    }

    public void setPlayerA(Integer c,Integer r){ //设置A玩家的落子位置
        lock.lock();
        try{
            this.playerA.setC(c);
            this.playerA.setR(r);
        }finally {
            lock.unlock();
        }
    }
    public void setPlayerB(Integer c,Integer r){ //设置B玩家落子位置
        lock.lock();
        try{
            this.playerB.setC(c);
            this.playerB.setR(r);
        }finally {
            lock.unlock();
        }
    }
    public void setNextStepA(boolean nextStepA){ //设置A玩家当前落子的状态
        lock.lock();
        try{
            this.nextStepA = nextStepA;
        }finally {
            lock.unlock();
        }
    }
    public void setNextStepB(boolean nextStepB){ //设置B玩家当前落子的状态
        lock.lock();
        try {
            this.nextStepB = nextStepB;
        }finally {
            lock.unlock();
        }
    }

    private void judge(int row,int col,int player){ //根据board来判断当前落子之后局面的情况
        //如果是想将 5个棋子，我觉得可以返回一个list,然后在前端去画一个棋子的阴影，当然后面可以再加
        // 定义四个检查方向：水平、垂直、主对角线、副对角线
        int[][] directions = {
            {0, 1},   // 水平 →
            {1, 0},   // 垂直 ↓
            {1, 1},   // 主对角线 \;
            {1, -1}   // 副对角线 /;
        };

        // 遍历每个方向
        for (int[] dir : directions) { //这种定义和写法和c++不太一样
            int dx = dir[0];
            int dy = dir[1];
            int count = 1; // 初始位置已经算作一个棋子

            // 正向检查（沿方向递增）
            for (int i = 1; i <= 4; i++) {
                int newRow = row + dx * i;
                int newCol = col + dy * i;
                // 检查新位置是否在棋盘范围内且属于当前玩家
                if (newRow > 0 && newRow < this.rows &&
                        newCol > 0 && newCol < this.cols &&
                        this.board[newRow][newCol] == player) {
                    count++;
                } else {
                    break;// 遇到非本方棋子或越界，停止检查
                }
            }

            // 反向检查（沿相反方向递减）
            for (int i = 1; i <= 4; i++) {
                int newRow = row - dx * i;
                int newCol = col - dy * i;
                // 检查新位置是否在棋盘范围内且属于当前玩家
                if (newRow > 0 && newRow < this.rows &&
                        newCol > 0 && newCol < this.cols &&
                        this.board[newRow][newCol] == player) {
                    count++;
                } else {
                    break;// 遇到非本方棋子或越界，停止检查
                }
            }

            // 如果当前方向累计达到5个棋子，判定胜利
            if (count >= 5) {
                this.status = "finished";
                this.loser = player == 1 ? "B" : "A";
                return;
            }
        }
    }
    private void sendAllMessage(String message){
        WebSocketServer.users.get(playerA.getId()).sendMessage(message);
        WebSocketServer.users.get(playerB.getId()).sendMessage(message);
    }
    private void sendMove(){

        lock.lock();
        try {
            JSONObject resp = new JSONObject();
            resp.put("event","move");
            if(currentPlayer == 1){
                //System.out.println("sendMove1 "+playerA.getC()+" "+playerA.getR());
                resp.put("col",playerA.getC());
                resp.put("row",playerA.getR());
                resp.put("currentPlayer","1");
            }else if(currentPlayer == 2){
                //System.out.println("sendMove2 "+playerB.getC()+" "+playerB.getR());
                resp.put("col",playerB.getC());
                resp.put("row",playerB.getR());
                resp.put("currentPlayer","2");
            }
            sendAllMessage(resp.toJSONString());
            nextStepA = nextStepB = false;
        }finally {
            lock.unlock();
        }
    }
    private void sendResult(){
        JSONObject resp = new JSONObject();
        resp.put("event","result");
        resp.put("loser",loser);
        sendAllMessage(resp.toJSONString());
    }
    private boolean nextStep(){ //判断是否有输入
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        for(int i=0;i<50;i++){
            try{
                Thread.sleep(100);
                lock.lock();
                try{
                    if(currentPlayer == 1 && nextStepA){ //当前回合肯定有一个是要落子
                        return true;
                    }
                    if(currentPlayer == 2 && nextStepB){
                        return true;
                    }
                }finally {
                    lock.unlock();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return false;
    }
    @Override
    public void run() {
        for(int i=0;i<1000;i++){ //棋盘是 15*15的
            if(nextStep()){ //有输入
                //首先是向前端发送这个输入信息，必须把这个图画上
                sendMove();
                //然后再去判断
                lock.lock();
                try{
                    if(this.currentPlayer == 1){
                        judge(playerA.getR(),playerA.getC(),1);
                        if(status.equals("finished")){
                            sendResult();
                            break;
                        }
                        this.currentPlayer = 2; //改变一下游戏玩家
                    }else {
                        judge(playerB.getR(),playerB.getC(),2);
                        if(status.equals("finished")){
                            sendResult();
                            break;
                        }
                        this.currentPlayer = 1;
                    }

                }finally {
                    lock.unlock();
                }

            }else{ //当前玩家回合没有输入
                status = "finished";
                lock.lock();
                try {
                    if(this.currentPlayer == 1){
                        loser = "A";
                    }else if(this.currentPlayer == 2) {
                        loser = "B";
                    }
                } finally {
                    lock.unlock();
                }
                sendResult();
                break;
            }
        }
    }
}
